package com.yixin.hospital.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yixin.hospital.common.ApiResult;
import com.yixin.hospital.common.Constant;
import com.yixin.hospital.entity.bo.PageInfo;
import com.yixin.hospital.entity.domain.*;
import com.yixin.hospital.entity.dto.req.auditmanager.AddAuditFlowReqDTO;
import com.yixin.hospital.entity.dto.req.dept.DeptAddReqDTO;
import com.yixin.hospital.entity.dto.req.dept.DeptEditReqDTO;
import com.yixin.hospital.entity.dto.req.dept.TempDeptAddReqDTO;
import com.yixin.hospital.entity.vo.AuditFlowPresetVO;
import com.yixin.hospital.entity.vo.DeptVO;
import com.yixin.hospital.entity.vo.JobDutyVO;
import com.yixin.hospital.entity.vo.UserTmpDeptVO;
import com.yixin.hospital.enums.AuditDetailStatusEnum;
import com.yixin.hospital.enums.BusinessEnum;
import com.yixin.hospital.enums.FlowNoPrefixEnum;
import com.yixin.hospital.enums.MessageTypeEnum;
import com.yixin.hospital.service.*;
import com.yixin.hospital.service.extend.AuditFlowPresetExtendService;
import com.yixin.hospital.utils.JwtUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/dept")
@Api(value = "部门管理", tags = "部门管理")
@Slf4j
public class DeptController {

    @Resource
    DeptService deptService;
    @Resource
    UserService userService;
    @Resource
    UserTmpDeptService userTmpDeptService;
    @Resource
    WorkAddressService workAddressService;
    @Resource
    AuditFlowPresetExtendService auditFlowPresetExtendService;
    @Resource
    AuditFlowDetailService auditFlowDetailService;
    @Resource
    AuditFlowPresetService auditFlowPresetService;
    @Resource
    JobDutyService jobDutyService;

    @GetMapping("/list")
    @ApiOperation(value = "部门列表（树状）")
    public ApiResult list() {
        List<Dept> list = deptService.list();
        List<DeptVO> deptVOList = list.stream().map(dept -> {
            DeptVO deptVO = new DeptVO();
            BeanUtil.copyProperties(dept, deptVO);
            deptVO.setPid(dept.getPid());
            return deptVO;
        }).collect(Collectors.toList());
        for (DeptVO deptVO : deptVOList) {
            if (Objects.nonNull(deptVO.getManager())) {
                User user = userService.getById(deptVO.getManager());
                deptVO.setManagerName(user.getName());
                deptVO.setManagerPhone(user.getPhone());
            }
            if (deptVO.getPid() != 0) {
                Dept dept = deptService.getById(deptVO.getPid());
                deptVO.setPName(dept.getName());
            }
        }
        TreeNodeConfig nodeConfig = new TreeNodeConfig();
        List<Tree<Integer>> treeList = TreeUtil.build(deptVOList, 0, nodeConfig,
                (node, tree) -> {
                    tree.setId(node.getId().intValue());
                    tree.setParentId(node.getPid().intValue());
                    tree.setName(node.getName());
                    tree.putExtra("pid", node.getPid());
                    tree.putExtra("pName", node.getPName());
                    tree.putExtra("phone", node.getPhone());
                    tree.putExtra("managerName", node.getManagerName());
                    tree.putExtra("managerPhone", node.getManagerPhone());
                    tree.putExtra("manager", node.getManager());
                    tree.putExtra("address", node.getAddress());
                });
        return ApiResult.success(CollectionUtil.isEmpty(treeList) ? new ArrayList<>() : treeList);
    }

    @GetMapping("/dept-drop-list")
    @ApiOperation(value = "部门下拉框")
    public ApiResult deptDropList(@RequestParam(value = "page", required = false) Integer page,
                                  @RequestParam(value = "size", required = false, defaultValue = "300") Integer size) {
        if (Objects.nonNull(page)) {
            return ApiResult.success(deptService.page(Page.of(page, size)));
        } else {
            return ApiResult.success(deptService.list());
        }
    }

    @PostMapping("/add")
    @ApiOperation(value = "添加部门")
    public ApiResult add(@Valid @RequestBody DeptAddReqDTO deptAddReqDTO, HttpServletRequest request) {
        Dept dept = new Dept();
        dept.setPid(deptAddReqDTO.getPid());
        dept.setName(deptAddReqDTO.getName());
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));
        dept.setAddress(deptAddReqDTO.getAddress());
        dept.setPhone(deptAddReqDTO.getPhone());
        dept.setManager(deptAddReqDTO.getManager());
        dept.setCreatedBy(userName);
        dept.setUpdatedBy(userName);
        deptService.save(dept);
        return ApiResult.success();
    }

    @PutMapping("/edit")
    @ApiOperation(value = "编辑部门")
    public ApiResult edit(@Valid @RequestBody DeptEditReqDTO deptEditReqDTO, HttpServletRequest request) {
        Dept dept = new Dept();
        dept.setId(deptEditReqDTO.getId());
        dept.setName(deptEditReqDTO.getName());
        dept.setAddress(deptEditReqDTO.getAddress());
        dept.setPhone(deptEditReqDTO.getPhone());
        dept.setManager(deptEditReqDTO.getManager());
        dept.setPid(deptEditReqDTO.getPid());
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));
        dept.setUpdatedBy(userName);
        deptService.updateById(dept);
        return ApiResult.success();
    }

    @DeleteMapping("/remove/{id}")
    @ApiOperation(value = "删除部门")
    public ApiResult remove(@PathVariable int id) {
        deptService.removeById(id);
        return ApiResult.success();
    }

    @PostMapping("/add-temp-dept")
    @ApiOperation(value = "临时部门申请")
    public ApiResult<?> addTempDept(@Valid @RequestBody TempDeptAddReqDTO tempDeptAddReqDTO, HttpServletRequest request) {
        Long userId = JwtUtil.getUserId(request.getHeader(Constant.AUTHORIZATION));
        String userName = JwtUtil.getName(request.getHeader(Constant.AUTHORIZATION));
        UserTmpDept userTmpDept = new UserTmpDept();
        userTmpDept.setUserId(userId);
        userTmpDept.setDeptId(tempDeptAddReqDTO.getDeptId());
        userTmpDept.setWorkAddressId(tempDeptAddReqDTO.getWorkAddressId());
        userTmpDept.setExpiration(tempDeptAddReqDTO.getExpiration());
        userTmpDept.setCreatedBy(userName);
        userTmpDeptService.save(userTmpDept);
        saveAudit(userId, userName, "ATD" + userTmpDept.getId().toString(), tempDeptAddReqDTO.getAuditUserIds());
        return ApiResult.success();
    }

    private void saveAudit(Long userId, String userName, String code, List<Long> auditUserIds) {
        // 添加审批流
        AddAuditFlowReqDTO addAuditFlowReqDTO = new AddAuditFlowReqDTO();
        addAuditFlowReqDTO.setTitle(FlowNoPrefixEnum.APPLY_TMP_DEPT.getMsg());
        addAuditFlowReqDTO.setBusinessCode(BusinessEnum.APPLY_TMP_DEPT.getCode());
        addAuditFlowReqDTO.setAuditUserIds(auditUserIds);
        addAuditFlowReqDTO.setUserId(userId);
        addAuditFlowReqDTO.setUserName(userName);
        addAuditFlowReqDTO.setFlowNo(code);
        addAuditFlowReqDTO.setMessageType(MessageTypeEnum.APPLY_TMP_DEPT.getCode());

        auditFlowPresetExtendService.addAuditFlow(addAuditFlowReqDTO);
    }

    @GetMapping("/user-temp-dept-list")
    @ApiOperation(value = "临时部门申请记录(自己看)")
    public ApiResult<?> userTempDeptList(@RequestParam int currentPage, @RequestParam int pageSize, HttpServletRequest request) {
        Long userId = JwtUtil.getUserId(request.getHeader(Constant.AUTHORIZATION));
        Page<UserTmpDept> page = userTmpDeptService.page(Page.of(currentPage, pageSize), new LambdaQueryWrapper<UserTmpDept>().eq(UserTmpDept::getUserId, userId).orderByDesc(UserTmpDept::getCreatedTime));
        List<UserTmpDeptVO> userTmpDeptVOList = new ArrayList<>();
        List<UserTmpDept> records = page.getRecords();
        for (UserTmpDept record : records) {
            UserTmpDeptVO userTmpDeptVO = new UserTmpDeptVO();
            BeanUtils.copyProperties(record, userTmpDeptVO);
            userTmpDeptVO.setUserName(userService.getById(record.getUserId()).getName());
            userTmpDeptVO.setDeptName(deptService.getById(record.getDeptId()).getName());
            userTmpDeptVO.setWorkAddressName(workAddressService.getById(record.getWorkAddressId()).getName());
            userTmpDeptVOList.add(userTmpDeptVO);

            AuditFlowPreset auditFlowPreset = auditFlowPresetService.getOne(new LambdaQueryWrapper<AuditFlowPreset>().eq(AuditFlowPreset::getBusinessCode, BusinessEnum.APPLY_TMP_DEPT.getCode()));
            List<AuditFlowDetail> auditFlowDetailList = auditFlowDetailService.list(new LambdaQueryWrapper<AuditFlowDetail>().eq(AuditFlowDetail::getFlowNo, "ATD" + userTmpDeptVO.getId()));
            String[] jobDutyList = auditFlowPreset.getJobDuty().split(",");

            AuditFlowPresetVO auditFlowPresetVO = new AuditFlowPresetVO();
            auditFlowPresetVO.setBusinessCode(BusinessEnum.APPLY_TMP_DEPT.getCode());
            auditFlowPresetVO.setBusinessName(BusinessEnum.APPLY_TMP_DEPT.getMsg());
            List<JobDutyVO> jobDutyVOList = new ArrayList<>();
            for (int i = 0; i < auditFlowDetailList.size(); i++) {
                JobDutyVO jobDutyVO = new JobDutyVO();
                jobDutyVO.setId(Long.valueOf(jobDutyList[i]));
                JobDuty jobDuty = jobDutyService.getById(Long.valueOf(jobDutyList[i]));
                jobDutyVO.setName(jobDuty.getName());
                AuditFlowDetail auditFlowDetail = auditFlowDetailList.get(i);
                jobDutyVO.setAuditUser(userService.getById(auditFlowDetail.getAuditUserId()));
                List<User> userListByJobDuty = userService.list(new LambdaQueryWrapper<User>().like(User::getJobDuty, jobDuty.getId()));
                userService.list().stream().filter(user -> {
                    String[] jobDutyListByUser = user.getJobDuty().split(",");
                    for (String s : jobDutyListByUser) {
                        if (Objects.equals(s, jobDuty.getId())) return true;
                    }
                    return false;
                });
                jobDutyVO.setAuditAvailableUserList(userListByJobDuty);
                jobDutyVOList.add(jobDutyVO);
            }
            auditFlowPresetVO.setJobDutyList(jobDutyVOList);
            userTmpDeptVO.setAuditFlowDetail(auditFlowPresetVO);

        }

        PageInfo<UserTmpDeptVO> pageInfo = new PageInfo<>();
        BeanUtils.copyProperties(page, pageInfo);
        pageInfo.setRecords(userTmpDeptVOList);
        return ApiResult.success(pageInfo);
    }

    @GetMapping("/all-user-temp-dept-list")
    @ApiOperation(value = "临时部门申请记录(管理员看)")
    public ApiResult<?> allUserTempDeptList(@RequestParam int currentPage, @RequestParam int pageSize, HttpServletRequest request) {
        Long userId = JwtUtil.getUserId(request.getHeader(Constant.AUTHORIZATION));
        Page<UserTmpDept> page = userTmpDeptService.page(Page.of(currentPage, pageSize), new LambdaQueryWrapper<UserTmpDept>().orderByDesc(UserTmpDept::getCreatedTime));
        List<UserTmpDeptVO> userTmpDeptVOList = new ArrayList<>();
        List<UserTmpDept> records = page.getRecords();
        for (UserTmpDept record : records) {
            UserTmpDeptVO userTmpDeptVO = new UserTmpDeptVO();
            BeanUtils.copyProperties(record, userTmpDeptVO);
            userTmpDeptVO.setUserName(userService.getById(record.getUserId()).getName());
            userTmpDeptVO.setDeptName(deptService.getById(record.getDeptId()).getName());
            userTmpDeptVO.setWorkAddressName(workAddressService.getById(record.getWorkAddressId()).getName());


            // 查询用户是否能审批
            LambdaUpdateWrapper<AuditFlowDetail> wrapper = new LambdaUpdateWrapper<>();
            wrapper.eq(AuditFlowDetail::getFlowNo, "ATD" + record.getId());
            wrapper.eq(AuditFlowDetail::getStatus, AuditDetailStatusEnum.AUDIT_ME.getCode());
            AuditFlowDetail auditFlowDetail = auditFlowDetailService.getOne(wrapper);
            if (Objects.nonNull(auditFlowDetail)) {
                if (userId.equals(auditFlowDetail.getAuditUserId())) {
                    userTmpDeptVO.setCanAudit(true);
                }
            }

            userTmpDeptVOList.add(userTmpDeptVO);
        }
        PageInfo<UserTmpDeptVO> pageInfo = new PageInfo<>();
        BeanUtils.copyProperties(page, pageInfo);
        pageInfo.setRecords(userTmpDeptVOList);
        return ApiResult.success(pageInfo);
    }
}
